using DocumentCreationSystem.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Text;
using System.Text.Json;

namespace DocumentCreationSystem.Services;

/// <summary>
/// DeepSeek AI服务实现
/// </summary>
public class DeepSeekService : IAIService
{
    private readonly IConfiguration _configuration;
    private readonly ILogger _logger;
    private readonly HttpClient _httpClient;
    private readonly string _apiKey;
    private readonly string _baseUrl;
    private readonly List<AIModel> _availableModels;
    private AIModel? _currentModel;

    public DeepSeekService(IConfiguration configuration, ILogger logger)
    {
        _configuration = configuration;
        _logger = logger;
        _httpClient = new HttpClient();
        
        _apiKey = configuration["ApiKey"] ?? "";
        _baseUrl = configuration["BaseUrl"] ?? "https://api.deepseek.com";
        
        _availableModels = new List<AIModel>();
        
        InitializeModels();
        ConfigureHttpClient();
    }

    private void InitializeModels()
    {
        // DeepSeek可用模型列表
        _availableModels.AddRange(new[]
        {
            new AIModel
            {
                Id = "deepseek-chat",
                Name = "DeepSeek-Chat",
                Provider = "DeepSeek",
                Description = "主要对话模型 - 适合文本创作和对话",
                IsAvailable = true,
                MaxTokens = 32768
            },
            new AIModel
            {
                Id = "deepseek-coder",
                Name = "DeepSeek-Coder",
                Provider = "DeepSeek",
                Description = "代码生成模型 - 专门用于编程",
                IsAvailable = true,
                MaxTokens = 16384
            },
            new AIModel
            {
                Id = "deepseek-reasoner",
                Name = "DeepSeek-Reasoner",
                Provider = "DeepSeek",
                Description = "推理模型 - 适合复杂逻辑推理",
                IsAvailable = true,
                MaxTokens = 32768
            }
        });

        // 设置默认模型
        var defaultModelId = _configuration["DefaultModel"] ?? "deepseek-chat";
        _currentModel = _availableModels.FirstOrDefault(m => m.Id == defaultModelId) ?? _availableModels.First();
    }

    private void ConfigureHttpClient()
    {
        _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "DocumentCreationSystem/1.0");
        _httpClient.Timeout = TimeSpan.FromSeconds(120); // 120秒，符合API请求最佳实践
    }

    public async Task<List<AIModel>> GetAvailableModelsAsync()
    {
        try
        {
            // 检查模型可用性
            foreach (var model in _availableModels)
            {
                model.IsAvailable = await CheckModelAvailabilityAsync(model.Id);
            }

            return _availableModels.Where(m => m.IsAvailable).ToList();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取DeepSeek可用模型失败");
            return _availableModels;
        }
    }

    private async Task<bool> CheckModelAvailabilityAsync(string modelId)
    {
        try
        {
            // 发送简单的测试请求来检查模型可用性
            var request = new
            {
                model = modelId,
                messages = new[]
                {
                    new { role = "system", content = "You are a helpful assistant." },
                    new { role = "user", content = "Hello!" }
                },
                max_tokens = 10,
                stream = false
            };

            var json = JsonSerializer.Serialize(request);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync($"{_baseUrl}/chat/completions", content);
            return response.IsSuccessStatusCode;
        }
        catch
        {
            return false;
        }
    }

    public async Task<bool> SetCurrentModelAsync(string modelId)
    {
        var model = _availableModels.FirstOrDefault(m => m.Id == modelId);
        if (model == null)
        {
            _logger.LogWarning($"DeepSeek模型不存在: {modelId}");
            return false;
        }

        // 先设置模型，然后可选地检查可用性
        _currentModel = model;
        _logger.LogInformation($"设置DeepSeek模型: {model.Name}");

        // 异步检查模型可用性，但不阻塞设置过程
        _ = Task.Run(async () =>
        {
            try
            {
                var isAvailable = await CheckModelAvailabilityAsync(modelId);
                if (isAvailable)
                {
                    _logger.LogInformation($"DeepSeek模型 {model.Name} 可用性验证成功");
                }
                else
                {
                    _logger.LogWarning($"DeepSeek模型 {model.Name} 可用性验证失败，但模型已设置");
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, $"DeepSeek模型 {model.Name} 可用性检查异常，但模型已设置");
            }
        });

        return true;
    }

    public AIModel? GetCurrentModel()
    {
        return _currentModel;
    }

    public async Task<string> GenerateTextAsync(string prompt, int maxTokens = 2000, float temperature = 0.7f)
    {
        if (_currentModel == null)
        {
            throw new InvalidOperationException("未设置当前DeepSeek模型");
        }

        try
        {
            var request = new
            {
                model = _currentModel.Id,
                messages = new[]
                {
                    new { role = "system", content = "You are a helpful assistant." },
                    new { role = "user", content = prompt }
                },
                max_tokens = Math.Min(maxTokens, _currentModel.MaxTokens),
                temperature = Math.Max(0.1f, Math.Min(1.0f, temperature)),
                stream = false
            };

            var json = JsonSerializer.Serialize(request);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync($"{_baseUrl}/chat/completions", content);
            response.EnsureSuccessStatusCode();

            var responseJson = await response.Content.ReadAsStringAsync();
            var result = JsonSerializer.Deserialize<DeepSeekResponse>(responseJson);

            if (result?.Choices?.Length > 0)
            {
                return result.Choices[0].Message.Content ?? "";
            }

            throw new Exception("DeepSeek API返回空响应");
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "DeepSeek API请求失败");
            throw new Exception($"DeepSeek API请求失败: {ex.Message}");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "DeepSeek文本生成失败");
            throw;
        }
    }

    public async Task<string> PolishTextAsync(string text, string style = "通用")
    {
        var prompt = $@"请对以下文本进行润色，要求：
1. 保持原意不变
2. 提升语言表达质量
3. 风格：{style}
4. 确保语法正确、表达流畅

原文：
{text}

请直接返回润色后的文本，不要添加任何解释。";

        return await GenerateTextAsync(prompt, text.Length + 500, 0.3f);
    }

    public async Task<string> ExpandTextAsync(string text, int targetLength, string? context = null)
    {
        var contextInfo = !string.IsNullOrEmpty(context) ? $"\n\n上下文信息：\n{context}" : "";
        
        var prompt = $@"请对以下文本进行扩写，要求：
1. 保持原有内容和风格
2. 增加细节描写和深度
3. 目标长度约{targetLength}字
4. 保持逻辑连贯性{contextInfo}

原文：
{text}

请直接返回扩写后的文本。";

        return await GenerateTextAsync(prompt, targetLength + 500, 0.7f);
    }

    public async Task<ConsistencyCheckResult> CheckConsistencyAsync(string currentText, string previousContext)
    {
        var prompt = $@"请检查以下当前文本与之前上下文的一致性，重点关注：
1. 人物性格和行为是否一致
2. 情节发展是否合理
3. 时间线是否正确
4. 设定是否矛盾

请简要分析并给出一致性评分（0-1），以及发现的问题和建议。

之前的上下文：
{previousContext}

当前文本：
{currentText}";

        try
        {
            var response = await GenerateTextAsync(prompt, 2000, 0.3f);

            // 简单的文本解析，提取一致性信息
            var isConsistent = !response.ToLower().Contains("不一致") && !response.ToLower().Contains("矛盾");
            var confidenceScore = ExtractConfidenceScore(response);

            return new ConsistencyCheckResult
            {
                IsConsistent = isConsistent,
                ConfidenceScore = confidenceScore,
                Issues = ExtractIssues(response),
                Suggestions = ExtractSuggestions(response)
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "DeepSeek一致性检查失败");
            return new ConsistencyCheckResult
            {
                IsConsistent = false,
                ConfidenceScore = 0.0f,
                Issues = new List<string> { $"检查过程出错: {ex.Message}" },
                Suggestions = new List<string> { "建议重新进行一致性检查" }
            };
        }
    }

    public async Task<string> GenerateChapterAsync(string outline, string? context = null, int targetWordCount = 6500)
    {
        var contextInfo = !string.IsNullOrEmpty(context) ? $"\n\n=== 参考信息 ===\n{context}" : "";

        var prompt = $@"你是一位专业的小说作家，现在需要根据章节细纲创作小说章节内容。

=== 重要：必须严格按照以下章节细纲进行创作 ===
{outline}

=== 字数要求（必须严格遵守）===
**目标字数：{targetWordCount}字**
- 最少不能低于{(int)(targetWordCount * 0.9)}字
- 最多不能超过{(int)(targetWordCount * 1.1)}字
- 请在创作过程中时刻关注字数，确保达到目标字数
- 如果内容不够，请增加细节描写、心理描写、环境描写等
- 如果内容过多，请适当精简，但不能删除关键情节

=== 创作要求 ===
1. **严格按照上述章节细纲的场景、人物、剧情发展进行创作**
2. **必须达到{targetWordCount}字的目标字数，这是硬性要求**
3. 保持小说的连贯性和可读性
4. 注意人物性格和情节发展的一致性
5. 只返回章节正文内容，不要标题和其他说明
6. **确保章节内容与细纲中描述的场景、冲突、人物发展完全一致**
7. **在创作时要充分展开情节，增加对话、动作、心理、环境等描写来达到字数要求**{contextInfo}

=== 创作指导 ===
为了达到{targetWordCount}字的要求，请注意：
- 详细描写人物的外貌、表情、动作
- 丰富环境和场景的描述
- 增加人物内心独白和心理活动
- 扩展对话内容，让对话更自然生动
- 添加适当的背景信息和回忆片段
- 细致描写战斗、冲突等关键场面

请开始创作章节正文：";

        return await GenerateTextAsync(prompt, Math.Max(targetWordCount + 2000, 8000), 0.8f);
    }

    public async Task<string> GenerateOutlineAsync(string description, string outlineType)
    {
        var prompt = $@"请根据以下描述生成{outlineType}大纲：

描述：
{description}

要求：
1. 结构清晰，层次分明
2. 内容详细，便于后续创作
3. 符合{outlineType}的特点和要求
4. 包含主要情节点和发展脉络

请生成详细的大纲内容：";

        return await GenerateTextAsync(prompt, 3000, 0.7f);
    }

    private float ExtractConfidenceScore(string response)
    {
        try
        {
            // 尝试从响应中提取置信度分数
            var lines = response.Split('\n');
            foreach (var line in lines)
            {
                if (line.Contains("评分") || line.Contains("置信度") || line.Contains("分数"))
                {
                    var numbers = System.Text.RegularExpressions.Regex.Matches(line, @"0\.\d+|\d+\.\d+");
                    if (numbers.Count > 0)
                    {
                        if (float.TryParse(numbers[0].Value, out var score))
                        {
                            return Math.Max(0.0f, Math.Min(1.0f, score));
                        }
                    }
                }
            }
            return 0.7f; // 默认置信度
        }
        catch
        {
            return 0.7f;
        }
    }

    private List<string> ExtractIssues(string response)
    {
        var issues = new List<string>();
        try
        {
            var lines = response.Split('\n');
            bool inIssuesSection = false;

            foreach (var line in lines)
            {
                var trimmedLine = line.Trim();
                if (trimmedLine.Contains("问题") || trimmedLine.Contains("矛盾") || trimmedLine.Contains("不一致"))
                {
                    inIssuesSection = true;
                    continue;
                }

                if (inIssuesSection && !string.IsNullOrWhiteSpace(trimmedLine))
                {
                    if (trimmedLine.Contains("建议") || trimmedLine.Contains("改进"))
                    {
                        break;
                    }
                    issues.Add(trimmedLine);
                }
            }
        }
        catch
        {
            // 忽略解析错误
        }

        return issues.Any() ? issues : new List<string>();
    }

    private List<string> ExtractSuggestions(string response)
    {
        var suggestions = new List<string>();
        try
        {
            var lines = response.Split('\n');
            bool inSuggestionsSection = false;

            foreach (var line in lines)
            {
                var trimmedLine = line.Trim();
                if (trimmedLine.Contains("建议") || trimmedLine.Contains("改进") || trimmedLine.Contains("优化"))
                {
                    inSuggestionsSection = true;
                    continue;
                }

                if (inSuggestionsSection && !string.IsNullOrWhiteSpace(trimmedLine))
                {
                    suggestions.Add(trimmedLine);
                }
            }
        }
        catch
        {
            // 忽略解析错误
        }

        return suggestions.Any() ? suggestions : new List<string> { "建议人工检查内容质量" };
    }

    public async Task<List<CharacterInfo>> ExtractCharacterInfoAsync(string text)
    {
        var prompt = $@"请从以下文本中提取角色信息，以JSON格式返回，包含：
- name: 角色名称
- attributes: 属性信息（如境界、修为等）
- skills: 技能列表
- equipment: 装备列表
- description: 角色描述

文本内容：
{text}";

        try
        {
            var response = await GenerateTextAsync(prompt, 3000, 0.3f);

            // 尝试解析JSON响应
            var jsonStart = response.IndexOf('[');
            var jsonEnd = response.LastIndexOf(']');

            if (jsonStart >= 0 && jsonEnd > jsonStart)
            {
                var jsonStr = response.Substring(jsonStart, jsonEnd - jsonStart + 1);
                var characters = JsonSerializer.Deserialize<List<CharacterInfo>>(jsonStr, new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                });

                return characters ?? new List<CharacterInfo>();
            }

            return new List<CharacterInfo>();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "DeepSeek角色信息提取失败");
            return new List<CharacterInfo>();
        }
    }
}

/// <summary>
/// DeepSeek API响应模型
/// </summary>
public class DeepSeekResponse
{
    public string Id { get; set; } = "";
    public string Object { get; set; } = "";
    public long Created { get; set; }
    public string Model { get; set; } = "";
    public DeepSeekChoice[] Choices { get; set; } = Array.Empty<DeepSeekChoice>();
    public DeepSeekUsage Usage { get; set; } = new();
}

public class DeepSeekChoice
{
    public int Index { get; set; }
    public DeepSeekMessage Message { get; set; } = new();
    public string FinishReason { get; set; } = "";
}

public class DeepSeekMessage
{
    public string Role { get; set; } = "";
    public string Content { get; set; } = "";
}

public class DeepSeekUsage
{
    public int PromptTokens { get; set; }
    public int CompletionTokens { get; set; }
    public int TotalTokens { get; set; }
}
